package com.bjy.qa.agent.tester;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bjy.qa.agent.enumtype.CatalogType;
import com.bjy.qa.agent.enumtype.ConditionEnum;
import com.bjy.qa.agent.enumtype.RunningModeStatus;
import com.bjy.qa.agent.tester.handler.perf.PerfTesterStepHandler;
import com.bjy.qa.agent.tester.handler.perf.PerfTesterTaskBootThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.ITestContext;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.bjy.qa.agent.tester.SuiteListener.runningTestsMap;

/**
 * 性能测试执行器
 */
public class PerfTester {
    private static final Logger logger = LoggerFactory.getLogger(PerfTester.class);

    @DataProvider(name = "caseInfo", parallel = false)
    public Object[][] getTestData(ITestContext context) {
        JSONObject dataInfo = JSON.parseObject(context.getCurrentXmlTest().getParameter("casesInfo"));
        List<JSONObject> dataProvider = new ArrayList<>();
        JSONObject caseInfo = new JSONObject();
        caseInfo.put("ctype", CatalogType.PERFORMANCE_TEST_SCRIPT.getValue());
        caseInfo.put("rid", dataInfo.getInteger("rid"));
        caseInfo.put("cid", dataInfo.getInteger("cid"));
        caseInfo.put("pid", dataInfo.getInteger("pid"));
        caseInfo.put("scenario", dataInfo.getJSONObject("scenario"));
        caseInfo.put("scriptType", dataInfo.getInteger("scriptType"));
        caseInfo.put("generators", dataInfo.getJSONArray("generators"));
        caseInfo.put("name", dataInfo.getString("name"));
        caseInfo.put("content", dataInfo.getString("content"));
        caseInfo.put("gp", dataInfo.getJSONObject("gp"));
        caseInfo.put("conditionType", ConditionEnum.NONE.getValue()); // 性能测试不需要条件判断，默认设置为 none
        caseInfo.put("dataProvider", dataInfo.getString("dataProvider"));
        dataProvider.add(caseInfo);

        Object[][] testDataProvider = new Object[dataProvider.size()][];
        for (int i = 0; i < dataProvider.size(); i++) {
            testDataProvider[i] = new Object[]{dataProvider.get(i)};
        }

        return testDataProvider;
    }

    @Test(dataProvider = "caseInfo")
    public void run(JSONObject jsonObject) throws IOException {
        logger.info("运行性能脚本：{}", jsonObject);

        // 重复任务，忽略
        int rid = jsonObject.getInteger("rid"); // result id
        if (TaskManager.ridRunning(rid)) {
            logger.info("忽略重复（可能是网络原因导致）忽略！");
            return;
        }

        // 创建 PerfTesterStepHandler
        int ctype = jsonObject.getInteger("ctype"); // catalogType 分类类型 - 上报日志类型
        int cid = jsonObject.getInteger("cid"); // case id
        PerfTesterStepHandler perfTesterStepHandler = new PerfTesterStepHandler(ctype, cid, "", rid, RunningModeStatus.TESTING, "");

        // 设置全局参数
        JSONObject gp = jsonObject.getJSONObject("gp");
        perfTesterStepHandler.setGlobalParams(gp);

        // 将 DataProvider 传进来的数据，设置到全局参数中
        JSONObject testData = jsonObject.getJSONObject("testData");
        perfTesterStepHandler.setGlobalParams(testData);

        // 启动任务
        PerfTesterTaskBootThread bootThread = new PerfTesterTaskBootThread(jsonObject, perfTesterStepHandler);
        if (!runningTestsMap.containsKey(rid + "")) {
            logger.info("性能任务【{}】中断，跳过", bootThread.getName());
            return;
        }
        TaskManager.startBootThread(bootThread);

        // TODO: 2023/4/26 后续这里改成多线程并发的
        // 保证用例串行，等待这个用例运行完成
        try {
            bootThread.waitFinished();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 强制停止，则退出
        if (bootThread.getForceStop()) {
            logger.info("性能任务【{}】中断，跳过", bootThread.getName());
            return;
        }
        logger.info("性能任务【{}】完成", bootThread.getName());
    }
}
